package com.zxd.service.impl;

import com.zxd.common.exception.GeneralExceptionHandler;
import com.zxd.core.Constant;
import com.zxd.dao.FileDao;
import com.zxd.dao.MasterDao;
import com.zxd.dao.RoleRelationDao;
import com.zxd.entity.File;
import com.zxd.entity.Master;
import com.zxd.entity.Role;
import com.zxd.entity.RoleRelation;
import com.zxd.entity.vo.BaseVo;
import com.zxd.service.MasterService;
import com.zxd.utils.DateUtils;
import com.zxd.utils.Md5Util;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * MasterServiceImpl
 * Created by 涂奕恒 on 2018/10/19 0019 下午 4:35.
 */
@Service
public class MasterServiceImpl implements MasterService {

    @Autowired
    private MasterDao masterDao;

    @Autowired
    private RoleRelationDao roleRelationDao;

    @Autowired
    private FileDao fileDao;

    @Override
    public List<Master> findAll() {
        return masterDao.findAll();
    }

    @Override
    public Page<Master> find(int pageNum, int pageSize) {
        return masterDao.findAll(new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id"));
    }

    @Override
    public Page<Master> find(int pageNum) {
        return find(pageNum, Constant.PAGE_DEF_SIZE);
    }

    @Override
    public Master getById(int id) {
        return masterDao.findOne(id);
    }

    @Override
    @Transactional
    public void deleteById(int id) {
        Master master = new Master();
        master.setId(Constant.CHECK_STATUS_SUCCESS);

        for (File file : fileDao.findListByMasterId(id)) {
            file.setMaster(master);

            fileDao.save(file);
        }

        masterDao.delete(id);
    }

    @Override
    public Master create(Master master) {
        return masterDao.save(master);
    }

    @Override
    public Master update(Master master) {
        return masterDao.save(master);
    }

    @Override
    @Transactional
    public void deleteAll(int[] ids) {
        for (int id : ids) {
            deleteById(id);
        }
    }

    @Override
    public Master loginIn(HttpServletRequest request, String account, String password) {
        Master master = masterDao.findOneByAccount(account);

        if (null != master && master.getPassword().equals(Md5Util.md5(password))) {
            request.getSession().setAttribute(Constant.CURRENT_LOGIN_MASTER, master);

            // 将管理员的角色信息放入session
            // isMember为是否是管理员的标记，0=否，1=是
            int isMember = 1;
            for (RoleRelation roleRelation : roleRelationDao.findListByMasterId(master.getId())) {
                if (roleRelation.getRole().getId() == 2)
                    isMember = 0;
            }

            request.getSession().setAttribute("isMember", isMember);

            return master;
        }

        return null;
    }

    @Override
    public void loginOut(HttpServletRequest request) {
        request.getSession().removeAttribute(Constant.CURRENT_LOGIN_MASTER);
    }

    @Override
    public Integer modifyPwd(HttpServletRequest request, String newPwd) {
        try {
            Master master = (Master) request.getSession().getAttribute(Constant.CURRENT_LOGIN_MASTER);
            if (null != master) {
                master.setPassword(Md5Util.md5(newPwd));
                masterDao.save(master);

                loginOut(request);
                return 1;
            }
        } catch (Exception e) {
            GeneralExceptionHandler.log("修改密码失败", e);
        }
        return 0;
    }

    @Override
    public BaseVo getData(String keyWord, Integer pageNum, Integer pageSize) {
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map;
        List<RoleRelation> roleRelationList;
        List<Master> masterList = findListByParams(keyWord, pageNum, pageSize);

        if (pageNum > 1 && masterList.size() == 0) {
            masterList = findListByParams(keyWord, pageNum - 1, pageSize);
        }

        String roleName;
        for (Master master : masterList) {
            roleRelationList = roleRelationDao.findListByMasterId(master.getId());

            map = new HashMap<>();
            map.put("id", master.getId());
            map.put("roleId", roleRelationList.size() > 0 ? roleRelationList.get(0).getRole().getId() : "");

            roleName = roleRelationList.size() > 0 ? roleRelationList.get(0).getRole().getName() : "";
            switch (master.getStatus()) {
                case 1:
                    roleName += "（充值↑↑）";
                    break;
                case 2:
                    roleName += "（系统↑↑）";
                    break;
            }

            map.put("roleName", roleName);
            map.put("account", master.getAccount());
            map.put("name", master.getName());
            map.put("mobile", master.getMobile());
            map.put("sex", master.getSex());
            map.put("level", master.getLevel());
            map.put("status", master.getStatus());
            map.put("createTime", DateUtils.longToStringWithFormat(master.getCreateTime(), Constant.DEFAULT_TIME));

            list.add(map);
        }

        BaseVo baseVo = new BaseVo();
        baseVo.setCount(findListByParams(keyWord, 1, 100000).size());
        baseVo.setData(list);

        return baseVo;
    }

    private List<Master> findListByParams(final String keyWord, Integer pageNum, Integer pageSize) {
        return masterDao.findAll((root, query, cb) -> {
            Predicate result = null;
            List<Predicate> predicateList = new ArrayList<>();

            if (StringUtils.isNotBlank(keyWord)) {
                predicateList.add(cb.or(cb.like(root.get("account").as(String.class), "%" + keyWord + "%"),
                        cb.like(root.get("name").as(String.class), "%" + keyWord + "%"),
                        cb.like(root.get("mobile").as(String.class), "%" + keyWord + "%")));
            }

            predicateList.add(cb.notEqual(root.get("id").as(Integer.class), Constant.CHECK_STATUS_SUCCESS));
            predicateList.add(cb.equal(root.get("status").as(Integer.class), Constant.CHECK_STATUS_DEFAULT));

            if (predicateList.size() > 0) {
                result = cb.and(predicateList.toArray(new Predicate[]{}));
            }
            if (result != null) {
                query.where(result);
            }
            return query.getGroupRestriction();
        }, new PageRequest(pageNum - 1, pageSize, Sort.Direction.DESC, "id")).getContent();
    }

    @Override
    public Integer saveInfo(Master master, Integer roleId) {
        Master masterByName = masterDao.findOneByAccount(master.getAccount());

        if (null == master.getId()) {
            if (null != masterByName) {
                return -1;
            }
        } else {
            if (null != masterByName && !master.getId().equals(masterByName.getId())) {
                return -1;
            }
            master.setUpdateTime(System.currentTimeMillis());
        }

        masterDao.save(master);

        changeRoleRelation(master.getId(), roleId);

        return 1;
    }

    @Override
    public Integer batchDel(String ids) {
        for (String s : ids.split(",")) {
            deleteById(Integer.parseInt(s));
        }
        return 1;
    }

    @Override
    public Integer upStatus(Integer id) {
        Master master = masterDao.findOne(id);

        if (master.getLevel().equals(0)) {
            master.setLevel(1);
            master.setStatus(2);

            masterDao.save(master);

            changeRoleRelation(id, 3);
        } else {
            return -1;
        }

        return 1;
    }

    private void changeRoleRelation(Integer masterId, Integer roleId) {
        for (RoleRelation roleRelation : roleRelationDao.findListByMasterId(masterId)) {
            roleRelationDao.delete(roleRelation.getId());
        }

        if (null != roleId) {
            Role role = new Role();
            role.setId(roleId);

            Master master = new Master();
            master.setId(masterId);

            RoleRelation roleRelation = new RoleRelation();
            roleRelation.setMaster(master);
            roleRelation.setRole(role);

            roleRelationDao.save(roleRelation);
        }
    }
}